package es

import (
	"context"
	"fmt"
	"time"

	ESModel "go-weixin/common/es/model"

	"github.com/olivere/elastic/v7"
	"github.com/zeromicro/go-zero/core/logx"
)

type Es struct {
	client *elastic.Client
}

type ModelRepo interface {
	IndexMapping() string
	IndexName() string
}

func Conn(dns string, user string, password string) *elastic.Client {
	client, err := elastic.NewClient(
		elastic.SetURL(dns),
		elastic.SetBasicAuth(user, password),
		elastic.SetSniff(false),
	)
	if err != nil {
		logx.Error(err)
		panic(err.Error())
	} else {
		logx.Infof("es连接成功: %s", dns)
	}
	return client
}

// 生成索引
func (e Es) Migrations() error {
	var modelList []ModelRepo
	modelList = append(modelList, ESModel.NewDiaryESModel(), ESModel.NewGuitarESModel())
	for _, m := range modelList {
		err := e.CreateIndex(m.IndexMapping(), m.IndexName())
		if err != nil {
			return err
		}
	}
	return nil
}

func (e Es) CreateIndex(body string, indexName string) error {
	ctx, cannFunc := context.WithTimeout(context.Background(), time.Second*10)
	defer cannFunc()
	exists, err := e.client.IndexExists(indexName).Do(ctx)
	if err != nil {
		logx.Errorf("es索引判断 索引:%s, 异常:%v", indexName, err)
		return err
	}
	if !exists {
		createIndex, err := e.client.CreateIndex(indexName).BodyString(body).Do(ctx)
		if err != nil {
			logx.Error("es创建索引失败")
			return err
		}
		if createIndex.Acknowledged {
			logx.Infof("es索引%s创建成功", indexName)
		}
	}

	return nil
}

func (e Es) Insert(ctx context.Context, indexName string, jsonBody string) error {
	_, err := e.client.Index().Index(indexName).OpType("create").BodyJson(jsonBody).Refresh("true").Do(ctx)
	if err != nil {
		logx.Errorf("es插入失败, err: %s", err.Error())
		return err
	}
	return nil
}

func (e Es) GetLogById(ctx context.Context, Id string, indexName string) (*elastic.GetResult, error) {
	data, err := e.client.Get().Index(indexName).Id(Id).Do(ctx)
	if err != nil {
		logx.Errorf("es查询失败, err: %s", err.Error())
		return nil, err
	}
	return data, nil
}

func (e Es) SearchByQuery(ctx context.Context, jsonBody string, indexName string) (*elastic.SearchResult, error) {
	data, err := e.client.Search(indexName).Source(jsonBody).Do(ctx)
	if err != nil {
		logx.Errorf("es查询失败, err: %s", err.Error())
		return nil, err
	}
	return data, nil
}

func NewEs(host string, port int64, user string, password string) *Es {
	e := &Es{client: Conn(fmt.Sprintf("http://%s:%d", host, port), user, password)}
	e.Migrations()
	return e
}
